using System;

namespace Fadd.Components
{
	/// <summary>
	/// Provides components.
	/// </summary>
	public interface IComponentProvider
	{
		/// <summary>
		/// Gets or sets where the component provider is running.
		/// </summary>
		/// <remarks>
		/// Used together with <see cref="Component.RunAt"/> and <see cref="ComponentAttribute.RunAt"/>
		/// to determine if the component should be added or not.
		/// </remarks>
		string Location { get; set; }

		/// <summary>
		/// Get a component.
		/// </summary>
		/// <typeparam name="T">Interface type</typeparam>
		/// <returns>Component if registered, otherwise null.</returns>
		/// <remarks>
		/// Component will get created if needed.
		/// </remarks>
		/// <exception cref="CircularDependenciesException">Two components are dependent of each other, and therefore neither of them can be created.</exception>
		/// <exception cref="ConstructorMismatchException">Failed to find a suitable constructor.</exception>
		/// <exception cref="UnauthorizedAccessException">If component is internal but accessed from another assembly but it's own.</exception>
		T Get<T>() where T : class;

		/// <summary>
		/// Checks if the specified component interface have been added.
		/// </summary>
		/// <param name="interfaceType"></param>
		/// <returns>true if found; otherwise false.</returns>
		bool Contains(Type interfaceType);

		/// <summary>
		/// Get a component.
		/// </summary>
		/// <returns>Component if registered, otherwise null.</returns>
		/// <remarks>
		/// Component will get created if needed.
		/// </remarks>
		/// <exception cref="CircularDependenciesException">Two components are dependent of each other, and therefore neither of them can be created.</exception>
		/// <exception cref="ConstructorMismatchException">Failed to find a suitable constructor.</exception>
		/// <exception cref="UnauthorizedAccessException">If component is internal but accessed from another assembly but it's own.</exception>
		object Get(Type interfaceType);
	}
}